from helper import CallProcess

class BaseMemory(object):

    def __getattr__(self, attr):
        if attr.startswith('mem_'):
            _attr = 'get_' + attr
            if hasattr(self, _attr):
                return getattr(self, _attr)()
        raise AttributeError("No such attribute %s" % attr)

    def get_mem_wire(self):
        '''Wired: disabled for paging out memory size'''

    def get_mem_active(self):
        '''Active: recently referenced'''

    def get_mem_inactive(self):
        '''Inactive: recently not referenced'''

    def get_mem_phys(self):
        '''Total real memory available'''

    def get_mem_all(self):
        '''Total real memory managed'''

    def get_mem_cache(self):
        '''Cached: almost avail. for allocation'''

    def get_mem_free(self):
        '''Free: fully available for allocation'''

    def get_mem_gap_vm(self):
        '''Memory gap: UNKNOWN'''

    def get_mem_gap_sys(self):
        '''Memory gap: Kernel?'''

    def get_mem_gap_hw(self):
        '''Memory gap: Segment Mapping?!'''

    def get_mem_hw(self):
        '''Total real memory installed'''

    def get_mem_used(self):
        '''Logically used memory'''

    def get_mem_avail(self):
        '''Logically available memory'''

    def get_mem_total(self):
        '''Logically total memory'''

class BSDMemory(BaseMemory):
    def __init__(self):
        self.pagesize = self.get_pagesize()

    def _sysctl_vm(self, oid):

        cmd = '/sbin/sysctl -n ' + oid
        proc = CallProcess(cmd)
        proc()
        ret = proc.stdout.strip()
        return int(ret)

    def get_pagesize(self):
        oid = 'hw.pagesize'
        return self._sysctl_vm(oid)

    def get_mem_wire(self):
        oid = 'vm.stats.vm.v_wire_count'
        return self._sysctl_vm(oid) * self.pagesize

    def get_mem_active(self):
        oid = 'vm.stats.vm.v_active_count'
        return self._sysctl_vm(oid) * self.pagesize

    def get_mem_inactive(self):
        oid = 'vm.stats.vm.v_inactive_count'
        return self._sysctl_vm(oid) * self.pagesize

    def get_mem_phys(self):
        oid = 'hw.physmem'
        return self._sysctl_vm(oid)

    def get_mem_all(self):
        oid = 'vm.stats.vm.v_page_count'
        return self._sysctl_vm(oid) * self.pagesize

    def get_mem_cache(self):
        oid = 'vm.stats.vm.v_cache_count'
        return self._sysctl_vm(oid) * self.pagesize

    def get_mem_free(self):
        oid = 'vm.stats.vm.v_free_count'
        return self._sysctl_vm(oid) * self.pagesize

    def get_mem_gap_vm(self):
        return self.mem_all - (self.mem_wire + self.mem_active + 
                               self.mem_inactive + self.mem_cache + 
                               self.mem_free)

    def get_mem_gap_sys(self):
        return self.mem_phys - self.mem_all

    def get_mem_gap_hw(self):
        return self.mem_hw - self.mem_phys

    def get_mem_hw(self):
        #TODO: rouned
        return self.get_mem_phys()

    def get_mem_used(self):
        return self.mem_total - self.mem_avail

    def get_mem_avail(self):
        return self.mem_inactive + self.mem_cache + self.mem_free

    def get_mem_total(self):
        return self.get_mem_hw()

